RStorage = game.ReplicatedStorage;
local sharedLibs = RStorage.SharedLibs;
local oo = require(sharedLibs.BaseLib);

--- 封装在x,z平面上的AABB
local AABBXZ = oo.class();

function AABBXZ:constructor(minX, maxX, minZ, maxZ)
	assert(minX <= maxX);
	assert(minZ <= maxZ);
	
	self.minX = minX;
	self.maxX = maxX;

	self.minZ = minZ;
	self.maxZ = maxZ;
end

function AABBXZ:Clone()
	return AABBXZ.new(self.minX, self.maxX, self.minZ, self.maxZ);
end

function AABBXZ:ClampPt(pt)
	local x = math.clamp(pt.X, self.minX, self.maxX);
	local z = math.clamp(pt.Z, self.minZ, self.maxZ);
	local y = pt.Y;	
	return Vector3.new(x, y, z);
end

--- Check if pt is in AABBXZ
function AABBXZ:CheckPt(pt)
	if pt.X >= self.minX and pt.X <= self.maxX 
		and pt.Z >= self.minZ and pt.Z <= self.maxZ
	then
		return true;
	else
		return false;
	end
end

function AABBXZ:GetWidth()
	local ret = self.maxX - self.minX;
	assert(ret > 0);
	return ret;
end

function AABBXZ:GetHeight()
	local ret = self.maxZ - self.minZ;
	assert(ret > 0);
	return ret;
end

function AABBXZ.FromPart(part)
	local ori = part.Orientation;
	assert(ori.X == 0) assert(ori.Y == 0) assert(ori.Z == 0);
	local pos = part.Position;
	local halfSize = part.Size / 2;
	
	return AABBXZ.new(pos.X - halfSize.X
		, pos.X + halfSize.X
		, pos.Z - halfSize.Z
		, pos.Z + halfSize.Z);
end

function AABBXZ:Merge(other)
	self.minX = math.min(self.minX, other.minX)
	self.maxX = math.max(self.maxX, other.maxX)
	self.minZ = math.min(self.minZ, other.minZ)
	self.maxZ = math.max(self.maxZ, other.maxZ)
	return self;
end

--- 收缩AABB
function AABBXZ:Shrink(x, z)
	local halfWidth = (self.maxX - self.minX) / 2;
	assert(halfWidth > 0);
	assert(x < halfWidth);
	local halfheight = (self.maxZ - self.minZ) / 2;
	assert(halfheight > 0);
	assert(z < halfheight);
	
	self.minX = self.minX + x;
	self.maxX = self.maxX - x;

	self.minZ = self.minZ + z;
	self.maxZ = self.maxZ - z;
end

function AABBXZ:GetRandPtV3(y)
	y = y or 0;
	return Vector3.new(self.minX + math.random() * (self.maxX - self.minX)
		, y
		, self.minZ + math.random() * (self.maxZ - self.minZ));
end

--- 在AABB的靠近minX的边缘处随机取点
function AABBXZ:GetMinXPtV3(range, y)
	y = y or 0;
	return Vector3.new(self.minX + math.random() * range
		, y
		, self.minZ + math.random() * (self.maxZ - self.minZ));
end

--- 在AABB的靠近minX的边缘处随机取点
function AABBXZ:GetMaxXPtV3(range, y)
	y = y or 0;
	return Vector3.new(self.maxX - math.random() * range
		, y
		, self.minZ + math.random() * (self.maxZ - self.minZ));
end

return AABBXZ;